package com.xnx.bincker.leader.domain;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.xnx.bincker.leader.core.domain.IdEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.hibernate.validator.constraints.Length;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.util.*;

/**
 * 用户
 */
@EqualsAndHashCode(callSuper = true)
@Entity
@Data
public class User extends IdEntity implements UserDetails {
	private static final long serialVersionUID = 2467211835246497756L;

    /**
     * 用户名
     */
    @Update
    @Insert
	@Column(length = 16, nullable = false, unique = true)
	@NotBlank(message = "用户名不能为空", groups = ValidGroup.Insert.class)
	@Pattern(regexp = "^[\\d\\w_\u4e00-\u9fa5]{5,16}$", message = "用户名由5-16位的数字、中英文字符或下划线组成")
	private String username;

    /**
     * 用户昵称
     */
    @Update
    @Insert
	@Column(length = 32)
	@Length(min = 5, max = 32, message = "昵称字符长度必须大于五位且小于三十二")
	private String nickname;

    /**
     * 密码
     */
    @Insert
	private String password;

    /**
     * 手机号
     */
    @Update
    @Insert
	@Column(length = 11, unique = true)
	@Pattern(regexp = "^((13[0-9])|(14[57])|(15[0-3,5-9])|(17[035-8])|(18[0-9])|166|198|199|(147))\\d{8}$", message = "请输入真实有效的手机号")
	private String phoneNumber;

    /**
     * 邮箱
     */
    @Insert
    @Update
    @Email
	private String email;

	/**
	 * 账户到期时间
	 */
    @Insert
    @Update
	private Date accountExpiredDate;

	/**
	 * 是否锁定
	 */
    @Insert
    @Update
	@Column(columnDefinition = "bit(1) not null default false")
    @NotNull(groups = ValidGroup.Insert.class)
	private Boolean locked;

	/**
	 * 凭证(密码)过期时间
	 */
	@JsonIgnore
	private Date credentialsExpiredDate;

	/**
	 * 账户是否可用
	 */
    @Insert
    @Update
	@Column(columnDefinition = "bit(1) not null default true")
    @NotNull(groups = ValidGroup.Insert.class)
	private Boolean enabled;

	/**
	 * 角色列表
	 */
	@JsonIgnore
	@ManyToMany(cascade = {CascadeType.MERGE}, fetch = FetchType.EAGER)
	private Set<Role> roles = new HashSet<>();

	@JsonIgnore
	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		return roles;
	}

	@Override
	public String getPassword() {
		return password;
	}

	@Override
	public String getUsername() {
		return username;
	}

	@JsonIgnore
	@Override
	public boolean isAccountNonExpired() {
		if(accountExpiredDate == null) return true;
		return accountExpiredDate.getTime() > System.currentTimeMillis();
	}

	@JsonIgnore
	@Override
	public boolean isAccountNonLocked() {
		return !locked;
	}

	@JsonIgnore
	@Override
	public boolean isCredentialsNonExpired() {
		if(credentialsExpiredDate == null) return true;
		return credentialsExpiredDate.getTime() > System.currentTimeMillis();
	}

	@Override
	public boolean isEnabled() {
		return enabled == null ? true : enabled;
	}

	/**
	 * 是否拥有某角色
	 * @param code 角色Code
	 */
	public boolean hasRule(String code){
		code = code.toUpperCase();
		if(!code.startsWith("ROLE_")) code = "ROLE_" + code;
		for (Role role : roles) {
			if(role.getCode().equals(code)) return true;
		}
		return false;
	}
}
